﻿
using HalconDotNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace CLVisionHalconWorker
{
    public class HalconCaller
    {
        #region "API"
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath);

        public string ReadValue(string section, string key, string Filepath)
        {
            StringBuilder temp = new StringBuilder(1024);
            int i = GetPrivateProfileString(section, key, "", temp, 1024, Filepath);
            return temp.ToString();
        }
        #endregion

        #region 变量
        public HDevEngine myEngine;
        public HDevProgramCall programCall;

        private HDevProcedure runProcedure;
        public HDevProcedure RunProcedure { get => runProcedure; set => runProcedure = value; }

        private HDevProcedureCall retProcedureCall;

        private HTuple _InputIconicNames;
        private HTuple _InputCtrlNames;
        private HTuple _OutputIconicNames;
        private HTuple _OutputCtrlNames;
        private List<string> procedurePaths = new List<string>();
        public HTuple InputIconicNames { get => _InputIconicNames; set => _InputIconicNames = value; }
        public HTuple InputCtrlNames { get => _InputCtrlNames; set => _InputCtrlNames = value; }
        public HTuple OutputIconicNames { get => _OutputIconicNames; set => _OutputIconicNames = value; }
        public HTuple OutputCtrlNames { get => _OutputCtrlNames; set => _OutputCtrlNames = value; }
        public  List<string> ProcedurePaths { get => procedurePaths; set => procedurePaths = value; }


        #endregion

        /// <summary>
        /// 初始化Halcon引擎
        /// </summary>
        /// <param name="procedurePath">procedure路径</param>
        /// <param name="logPath">日志路径</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public virtual bool  InitHDevEngine(out int ErrorCode, out string ErrorText)
        {
            try
            {
                myEngine = new HDevEngine();
               

                //设置文档语言，要想获取文档参数，必须先设置语言
                myEngine.SetEngineAttribute("docu_language", "zh_CN");
                if (myEngine!=null)
                {
                    ErrorText = "InitHDevEngine Success! +yyyyyyy";
                }
                else
                {
                    ErrorText = "InitHDevEngine Success!";
                }
                ErrorCode = 0;
               // ErrorText = "InitHDevEngine Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "InitHDevEngine Fail!" + ex.Message;
                return false;
            }
        }
        /// <summary>
        /// 添加Procedure路径
        /// </summary>
        /// <param name="procedurePath">Procedure路径</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool AddProcedurePath(string procedurePath, out int ErrorCode, out string ErrorText)
        {
            try
            {
                ProcedurePaths.Add(procedurePath);
                if (myEngine != null)
                {
                    myEngine.AddProcedurePath(procedurePath);
                }
                else
                {
                    ErrorCode = -1;
                    ErrorText = "Engine为null";
                    return false;
                }
               
                ErrorCode = 0;
                ErrorText = "AddprocedurePath Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "AddprocedurePath Fail!" + ex.Message;
                return false;
            }
        }
        /// <summary>
        /// 添加Procedure路径数组
        /// </summary>
        /// <param name="procedurePath">Procedure路径</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool AddProcedurePath(string[] procedurePath, out int ErrorCode, out string ErrorText)
        {
            try
            {
                for (int i = 0; i < procedurePath.Length; i++)
                {
                    ProcedurePaths.Add(procedurePath[i]);
                    myEngine.AddProcedurePath(procedurePath[i]);
                }
                ErrorCode = 0;
                ErrorText = "AddprocedurePaths Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "AddprocedurePaths Fail!" + ex.Message;
                return false;
            }
        }
        /// <summary>
        /// 获取Procedure名称
        /// </summary>
        /// <param name="showProcedurePath">显示文件夹内部的Procedure名称</param>
        /// <param name="procedureNames">Procedure名称</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool GetProcedureNames(string[] showProcedurePath, out string[] procedureNames, out int ErrorCode, out string ErrorText, SearchOption searchOption = SearchOption.AllDirectories)
        {
            List<string> tempLs = new List<string>();
            try
            {
                for (int i = 0; i < ProcedurePaths.Count; i++)
                {
                    for (int m = 0; m < showProcedurePath.Length; m++)
                    {
                        if (ProcedurePaths[i] == showProcedurePath[m])
                        {
                            string[] files = Directory.GetFiles(ProcedurePaths[i], "*.hdvp", searchOption);
                            for (int j = 0; j < files.Length; j++)
                            {
                                string path = files[j];
                                string procedureName = Path.GetFileNameWithoutExtension(path);
                                tempLs.Add(procedureName);
                            }
                        }
                    }

                }
                procedureNames = tempLs.ToArray();
                ErrorCode = 0;
                ErrorText = "GetProcedureNames Success!";
                return true;
            }
            catch (Exception ex)
            {
                procedureNames = null;
                ErrorCode = -1;
                ErrorText = "GetProcedureNames Fail!" + ex.Message;
                return false;
            }
        }
        /// <summary>
        /// 加载Procedure
        /// </summary>
        /// <param name="procedureName">Procedure名称</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool LoadProcedure(string procedureName, out int ErrorCode, out string ErrorText)
        {
            try
            {
                runProcedure = new HDevProcedure(procedureName);
                retProcedureCall = new HDevProcedureCall(runProcedure);
                ErrorCode = 0;
                ErrorText = "LoadProcedure Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "LoadProcedure Fail!" + ex.Message;
                return false;
            }

        }
        /// <summary>
        /// 获取Procedure参数名称
        /// </summary>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool GetProcedureParNames(out int ErrorCode, out string ErrorText)
        {
            try
            {
                _InputIconicNames = runProcedure.GetInputIconicParamNames();
                _InputCtrlNames = runProcedure.GetInputCtrlParamNames();
                _OutputIconicNames = runProcedure.GetOutputIconicParamNames();
                _OutputCtrlNames = runProcedure.GetOutputCtrlParamNames();
                ErrorCode = 0;
                ErrorText = "GetProcedureParNames Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "GetProcedureParNames Fail!" + ex.Message;
                return false;
            }

        }
        /// <summary>
        /// 调用Procedure
        /// </summary>
        /// <param name="procedureName">Procedure名称</param>
        /// <param name="hObj_InputIconic">图像输入</param>
        /// <param name="hObj_OutputIconic">图像输出</param>
        /// <param name="hTuple_InputCtrl">控制输入</param>
        /// <param name="hTuple_OutputCtrl">控制输出</param>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool CallProcedure(string procedureName, HObject[] hObj_InputIconic, out HObject[] hObj_OutputIconic, HTuple hTuple_InputCtrl, out HTuple hTuple_OutputCtrl, out int ErrorCode, out string ErrorText)
        {
            hObj_OutputIconic = null;
            hTuple_OutputCtrl = null;

            if (this.RunProcedure.Name != procedureName)
            {
                LoadProcedure(procedureName, out ErrorCode, out ErrorText);
                if (ErrorCode == -1)
                {
                    return false;
                }
            }

            GetProcedureParNames(out ErrorCode, out ErrorText);
            if (ErrorCode == -1)
            {
                return false;
            }
            try
            {
                for (int i = 0; i < hObj_InputIconic?.Length; i++)
                {
                    HObject hObject = hObj_InputIconic[i];
                    string name = InputIconicNames[i].S;
                    retProcedureCall.SetInputIconicParamObject(name, hObject);
                }

                for (int i = 0; i < hTuple_InputCtrl?.Length; i++)
                {
                    retProcedureCall.SetInputCtrlParamTuple(InputCtrlNames[i].S, hTuple_InputCtrl[i]);
                }
                //运行 Procedure
                retProcedureCall.Execute();

                //创建 Temp_hObj_OutputIconic 集合和 Temp_hTuple_OutputCtrl，用于存储 Procedure 的输出结果
                List<HObject> Temp_hObj_OutputIconic = new List<HObject>();
                HTuple Temp_hTuple_OutputCtrl = new HTuple();

                //遍历输出结果，并存储值 Temp_hObj_OutputIconic 集合和 Temp_hTuple_OutputCtrl
                for (int i = 0; i < OutputIconicNames?.Length; i++)
                {
                    HObject hObject = retProcedureCall.GetOutputIconicParamObject(OutputIconicNames[i].S);
                    Temp_hObj_OutputIconic.Add(hObject);
                }

                for (int i = 0; i < OutputCtrlNames?.Length; i++)
                {
                    HTuple hTuple = retProcedureCall.GetOutputCtrlParamTuple(OutputCtrlNames[i].S);
                    Temp_hTuple_OutputCtrl[i] = hTuple;
                }
                //将存储结果输出
                hObj_OutputIconic = Temp_hObj_OutputIconic.ToArray();
                hTuple_OutputCtrl = Temp_hTuple_OutputCtrl;

                ErrorCode = 0;
                ErrorText = "CallProcedure Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "CallProcedure Fail!" + ex.Message;
                hObj_OutputIconic = null;
                hTuple_OutputCtrl = null;
                return false;
            }
        }

        public bool CallProcedure(string procedureName, HObject[] hObj_InputIconic, out HObject[] hObj_OutputIconic, HTupleVector hTuple_InputCtrl, out HTupleVector hTuple_OutputCtrl, out int ErrorCode, out string ErrorText)
        {
            hObj_OutputIconic = null;
            hTuple_OutputCtrl = null;

            //判断已经加载的procedure，是否是要运行的
            if (this.RunProcedure.Name != procedureName)
            {
                LoadProcedure(procedureName, out ErrorCode, out ErrorText);
                if (ErrorCode == -1)
                {
                    return false;
                }
            }

            //获取procedure的图标参数和控制参数名称
            GetProcedureParNames(out ErrorCode, out ErrorText);
            if (ErrorCode == -1)
            {
                return false;
            }
            //传参运行procedure
            try
            {
                for (int i = 0; i < hObj_InputIconic?.Length; i++)
                {
                    HObject hObject = hObj_InputIconic[i];
                    string name = InputIconicNames[i].S;
                    retProcedureCall.SetInputIconicParamObject(name, hObject);
                }

                for (int i = 0; i < hTuple_InputCtrl?.Length; i++)
                {
                    retProcedureCall.SetInputCtrlParamTuple(InputCtrlNames[i].S, hTuple_InputCtrl[i].T);
                }
                //运行 Procedure
                retProcedureCall.Execute();

                //创建 Temp_hObj_OutputIconic 集合和 Temp_hTuple_OutputCtrl，用于存储 Procedure 的输出结果
                List<HObject> Temp_hObj_OutputIconic = new List<HObject>();
                HTupleVector Temp_hTuple_OutputCtrl = new HTupleVector(1);

                //遍历输出结果，并存储值 Temp_hObj_OutputIconic 集合和 Temp_hTuple_OutputCtrl
                for (int i = 0; i < OutputIconicNames?.Length; i++)
                {
                    HObject hObject = retProcedureCall.GetOutputIconicParamObject(OutputIconicNames[i].S);
                    Temp_hObj_OutputIconic.Add(hObject);
                }

                for (int i = 0; i < OutputCtrlNames?.Length; i++)
                {
                    HTuple hTuple = retProcedureCall.GetOutputCtrlParamTuple(OutputCtrlNames[i].S);
                    Temp_hTuple_OutputCtrl[i] = new HTupleVector(hTuple);
                }
                //将存储结果输出
                hObj_OutputIconic = Temp_hObj_OutputIconic.ToArray();
                hTuple_OutputCtrl = Temp_hTuple_OutputCtrl;

                ErrorCode = 0;
                ErrorText = "CallProcedure Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "CallProcedure Fail!" + ex.Message;
                hObj_OutputIconic = null;
                hTuple_OutputCtrl = null;
                return false;
            }
        }


        /// <summary>
        /// 销毁引擎
        /// </summary>
        /// <param name="ErrorCode">错误代码</param>
        /// <param name="ErrorText">错误信息</param>
        /// <returns></returns>
        public bool DeInit(out int ErrorCode, out string ErrorText)
        {
            try
            {
                myEngine.Dispose();
                ErrorCode = 0;
                ErrorText = "DeInit Success!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "DeInit Fail!" + ex.Message;
                return false;
            }
        }
    }
}



